package edu.scau.ojforwarder.util;

import edu.scau.ojforwarder.bean.IError;
import edu.scau.ojforwarder.bean.NowcoderError;
import edu.scau.ojforwarder.bean.NowcoderStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;

@Component
public class NowcoderStatusManager {

    @Autowired
    private NowcoderClient nowcoderClient;

    private Map<String, NowcoderStatus> runIdStatusMap = new HashMap<>();

    private Map<String, NowcoderStatus> submissionIdStatusMap = new HashMap<>();

    private Logger logger = LoggerFactory.getLogger(NowcoderStatusManager.class);

    public synchronized void addStatus(String submissionId, NowcoderStatus status) {
        status.setSubmissionId(submissionId);
        submissionIdStatusMap.put(submissionId, status);
    }

    public synchronized NowcoderStatus getStatus(String submissionId) {
        try {
            return (NowcoderStatus) submissionIdStatusMap.get(submissionId).clone();
        } catch (Exception e) {
            logger.error("获取结果失败。", e);
            return null;
        }
    }

    public synchronized void addAssociation(String runId, String submissionId) {
        NowcoderStatus status = submissionIdStatusMap.get(submissionId);
        status.setRunId(runId);
        runIdStatusMap.put(runId, status);
    }

    public synchronized void updateStatus(NowcoderStatus status) {
        NowcoderStatus s = runIdStatusMap.get(status.getRunId());
        if (s != null) {
            s.setStatus(status.getStatus());
            s.setDesc(status.getDesc());
            s.setExeTime(status.getExeTime());
            s.setExeMemory(status.getExeMemory());
            s.setMemo(status.getMemo());
            switch (s.getStatus()) {
                case NowcoderStatus.PENDING:
                case NowcoderStatus.QUEUING: break;
                case "AC": s.setResult(0); break;
                case "PE": s.setResult(1); break;
                case "TLE": s.setResult(2); break;
                case "MLE": s.setResult(3); break;
                case "WA": s.setResult(4); break;
                case "RE": s.setResult(5); break;
                case "OLE": s.setResult(6); break;
                case "CE": s.setResult(7); break;
                case NowcoderStatus.SUBMIT_FAILED: s.setResult(21); break;
                case "OtherError": s.setResult(22); break;
            }
        }
    }

    public void updateStatus(String submissionId) {
        String runId = getStatus(submissionId).getRunId();
        try {
            NowcoderStatus status = nowcoderClient.getStatus(runId);
            updateStatus(status);
        } catch (Exception e) {
            logger.error("更新结果失败。", e);
        }
    }

    /**
     * 设置出错原因，只用于提交代码时产生的错误
     * @param submissionId
     * @param error
     */
    public synchronized void setError(String submissionId, IError error) {
        NowcoderStatus status = submissionIdStatusMap.get(submissionId);
        status.setStatus(NowcoderStatus.SUBMIT_FAILED);
        status.setDesc("提交失败");
        status.setError((NowcoderError) error);
        status.setResult(21);
    }
}
